package level

import (
	"reflect"

	"github.com/syndtr/goleveldb/leveldb/util"
)

// Append 切片增加.
func (p *Service) Append(key []byte, elems ...interface{}) {
	if len(elems) == 0 {
		return
	}

	mu := p.getMutex(key)

	mu.Lock()
	defer mu.Unlock()

	sk := []byte{ByteSlice}
	sk = append(sk, key...)

	for _, elem := range elems {
		elemKey := p.NextSequenceASC(sk)
		elemKey = append(sk, elemKey...)

		p.Put(elemKey, elem)
	}
}

// Slice 获取切片.
func (p *Service) Slice(key []byte, slice interface{}) {
	sliceValue := reflect.ValueOf(slice)
	if sliceValue.Kind() != reflect.Ptr {
		panic(ErrNotPtr)
	}

	sliceValue = sliceValue.Elem()
	if sliceValue.Kind() != reflect.Slice {
		panic(ErrNotSlice)
	}

	mu := p.getMutex(key)

	mu.Lock()
	defer mu.Unlock()

	data := reflect.Append(sliceValue)
	elemType := reflect.TypeOf(slice).Elem().Elem()
	isPtr := false

	if elemType.Kind() == reflect.Ptr {
		elemType = elemType.Elem()
		isPtr = true
	}

	sk := []byte{ByteSlice}
	sk = append(sk, key...)
	ran := util.BytesPrefix(sk)

	iter := p.DB.NewIterator(ran, nil)
	for iter.Next() {
		newElem := reflect.New(elemType)
		setValue(newElem, iter.Value())

		if isPtr {
			data = reflect.Append(data, newElem)
		} else {
			data = reflect.Append(data, newElem.Elem())
		}
	}

	sliceValue.Set(data)
}
